package com.gopay.bis.icbc.ebank.operation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpStatus;

import cn.com.infosec.util.Base64;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.exception.GopayException;

public class IcbcB2bQuery {

	private final static String REQDATA = "reqData=";
	// 订单查询地址
	private String url;
	// 超时时间
	private int timeout;
	// 设置编码
	private String sendEncoding;

	/**
	 * 截取返回消息体并做base64转码
	 * 
	 * @param String
	 * @return String
	 * 
	 * */
	public String decode(String responseBody) throws GopayException {
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
		try {
			responseBody = responseBody.substring(REQDATA.length());
			String plainMessage = "";
			plainMessage = new String(Base64.decode(new String(responseBody.getBytes("GBK"), "UTF-8")), "GBK");
			BankLogUtils.printB2BQueryBlackLog(baseMessage, plainMessage);
			return plainMessage;
		} catch (Exception e) {
			BankLogUtils.printB2BQueryExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6038);
		}

	}

	public synchronized String sendReq(Map<String, String> param) throws GopayException {
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setOutStlmCd(BankConstants.BANK_LOGO_ICBC); // 为了区分日志输出
		CloseableHttpClient httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(1, false)).build();
		HttpPost method = new HttpPost(param.get("queryUrl") + "?userID=" + param.get("userID")+ "&PackageID=" + param.get("PackageID") + "&SendTime="+ param.get("SendTime"));
		CloseableHttpResponse response = null;
		try {
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectionRequestTimeout(timeout).setConnectionRequestTimeout(timeout).build();
			method.setHeader(HTTP.USER_AGENT, "Rich Powered/1.0");
			method.setHeader("Connection","close");
			method.setConfig(requestConfig);
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			nvps.add(new BasicNameValuePair("Version", param.get("Version")));
			nvps.add(new BasicNameValuePair("TransCode", param.get("TransCode")));
			nvps.add(new BasicNameValuePair("BankCode", param.get("BankCode")));
			nvps.add(new BasicNameValuePair("GroupCIS", param.get("GroupCIS")));
			nvps.add(new BasicNameValuePair("ID", param.get("ID")));
			nvps.add(new BasicNameValuePair("PackageID", param.get("PackageID")));
			nvps.add(new BasicNameValuePair("Cert", ""));
			nvps.add(new BasicNameValuePair("reqData", param.get("reqData")));
			method.setEntity(new UrlEncodedFormEntity(nvps));
			int statusCode = 0;
			response = httpClient.execute(method);
			statusCode = response.getStatusLine().getStatusCode();
			HttpEntity responseEntity = response.getEntity();
			if(statusCode == HttpStatus.FORBIDDEN.value()){
				for(int i=0;i<2;i++){
					//工行403拒绝访问,休眠3秒再访问一次
					TimeUnit.SECONDS.sleep(3);
					response = httpClient.execute(method);
					statusCode = response.getStatusLine().getStatusCode();
					responseEntity = response.getEntity();
					if((statusCode!=HttpStatus.FORBIDDEN.value())||i==1){
						break;
					}
				}
			}					
			if (statusCode != HttpStatus.OK.value()) {
				BankLogUtils.printB2BHttpStatusCode(baseMessage, statusCode);
				return null;
			}
			String body = EntityUtils.toString(responseEntity);
			BankLogUtils.printB2BQuerySendLog(baseMessage, param);
			return body;
		} catch (Exception e) {
			BankLogUtils.printB2BQueryExceptionLog(baseMessage, e);
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6036);
		} finally {
			try {
				if (response != null)
					response.close();
			} catch (IOException e) {
				// we need nothing to catch.
			}
		}
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public void setSendEncoding(String sendEncoding) {
		this.sendEncoding = sendEncoding;
	}
}
